package com.duoec.dw.lineage.service.analyser.query;

import com.alibaba.druid.sql.ast.statement.SQLUnionOperator;
import com.alibaba.druid.sql.ast.statement.SQLUnionQuery;
import com.alibaba.druid.sql.ast.statement.SQLWithSubqueryClause;
import com.duoec.dw.lineage.dto.MultiTableLineageDto;
import com.duoec.dw.lineage.dto.TableFieldDependencyDto;
import com.duoec.dw.lineage.dto.TableFieldLineageDto;
import com.duoec.dw.lineage.dto.TableLineageDto;
import com.duoec.dw.lineage.exceptions.LineageAnalyseException;
import com.duoec.dw.lineage.core.utils.AnalyserUtils;
import com.google.common.collect.Lists;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.LinkedHashSet;
import java.util.List;

/**
 * @author xuwenzhen
 */
@Service
public class UnionQueryAnalyser extends BaseQueryAnalyser<SQLUnionQuery> {
    private static final Logger logger = LoggerFactory.getLogger(UnionQueryAnalyser.class);

    @Override
    public Class<SQLUnionQuery> getSelectQueryType() {
        return SQLUnionQuery.class;
    }

    /**
     * 解析 select语句
     *
     * @param sqlUnionQuery       需要解析的select
     * @param withAsTableLineages with-in
     * @return 当前select脚本的血缘关系
     */
    @Override
    public TableLineageDto analyse(SQLUnionQuery sqlUnionQuery, MultiTableLineageDto withAsTableLineages) {
        TableLineageDto dto = new TableLineageDto();
        sqlUnionQuery.getRelations().forEach(query -> {
            TableLineageDto queryLineageDto = hiveAnalyser.analyseQuery(query, withAsTableLineages);
            if (queryLineageDto == null) {
                return;
            }
            mergeGlobalDependencies(queryLineageDto);

            LinkedHashSet<TableFieldLineageDto> fields = dto.getFields();
            if (fields == null) {
                fields = queryLineageDto.getFields();
                dto.setFields(fields);
                return;
            }

            //合并字段
            if (fields.size() != queryLineageDto.getFields().size()) {
                throw new LineageAnalyseException("union字段数量不一致！数量分别为：" + fields.size() + "," + queryLineageDto.getFields().size());
            }

            List<TableFieldLineageDto> fieldList = Lists.newArrayList(fields);
            List<TableFieldLineageDto> newFieldList = Lists.newArrayList(queryLineageDto.getFields());

            SQLUnionOperator operator = sqlUnionQuery.getOperator();

            LinkedHashSet<TableFieldDependencyDto> dependencies = queryLineageDto.getDependencies();
            for (int i = 0; i < fieldList.size(); i++) {
                TableFieldLineageDto field = fieldList.get(i);
                TableFieldLineageDto newField;
//                if (operator == SQLUnionOperator.UNION_ALL) {
//                    newField = queryLineageDto.getFieldByName(field.getColName());
//                    if (newField == null) {
//                        throw new LineageAnalyseException("union序号[" + i + "]的字段名称无法匹配上：" + dto.getFullTableName() + "." + field.getColName() + "");
//                    }
//                } else {
//                }
                newField = newFieldList.get(i);
                if (newField.getColName() == null || (!newField.getColName().equals(field.getColName()) && operator != SQLUnionOperator.UNION_ALL)) {
                    logger.warn("union序号[{}]的字段名称不一致！[{}.{}}, {}.{}]", i, queryLineageDto.getFullTableName(), newField.getColName(), dto.getFullTableName(), field.getColName());
                }
                addAllDependencies(dependencies, field);
                addAllDependencies(newField.getDependencies(), field);
            }
        });

        //补全字段信息
        AnalyserUtils.fixFieldInfo(dto);
        return dto;
    }

    private void mergeGlobalDependencies(TableLineageDto queryLineageDto) {
        if (queryLineageDto == null) {
            return;
        }
        LinkedHashSet<TableFieldDependencyDto> dependencies = queryLineageDto.getDependencies();
        if (CollectionUtils.isEmpty(dependencies)) {
            return;
        }
        //如果不为空时，需要将它设置进字段里去
        queryLineageDto.getFields().forEach(field -> addAllDependencies(dependencies, field));
        dependencies.clear();
    }

    private void addAllDependencies(LinkedHashSet<TableFieldDependencyDto> dependencies, TableFieldLineageDto field) {
        if (CollectionUtils.isEmpty(dependencies)) {
            return;
        }
        LinkedHashSet<TableFieldDependencyDto> fieldDependencies = field.getDependencies();
        if (fieldDependencies == null) {
            fieldDependencies = new LinkedHashSet<>();
            field.setDependencies(fieldDependencies);
        }
        fieldDependencies.addAll(dependencies);
    }
}
